#include "test_cam.h"
#include "ocr_procs.h"
#include "pre_procs.h"
#include "bmp.h"
#include "common.h"
#include "char_recog.h"

int NUM_HID_CHAR = 50;

int NUM_TRAIN_FILE = 4;
int NUM_TEST_FILE = 2;

int main(int argc, char* argv[]) {

    int i;
    int h, w;
    unsigned long **pix;
    char* testFile = "testImg.bmp";
    char* trainFile = "trainImg.bmp";

    int c;
    double mse;
    double minMse, totalMse, avgMse;
    int autorun, test, train, loopTrain, trainingCase, trainingLoop, nLoop, check;

    autorun = test = train = loopTrain = trainingCase = check = 0;
    trainingLoop = 10;
    opterr = 0;

    while ((c = getopt(argc, argv, "a:t:r:l:c:")) != -1)
    {
        switch (c)
        {
            case 'a':
                autorun = 1;
                trainingLoop = atoi(optarg);
                if (trainingLoop < 0)
                    trainingLoop = 10;
                break;
            case 't':
                testFile = optarg;
                test = 1;
                break;
            case 'r':
                trainFile = optarg;
                train = 1;
                break;
            case 'l':
                nLoop = atoi(optarg);
                loopTrain = 1;
                break;
            case 'c':
                check = 1;
                trainFile = optarg;
                break;
//            case '?':
//                if (optopt == 't')
//                {
//                    printf("missing test filename\n");
//                }
//                else if (optopt == 'r')
//                {
//                    printf("missing train filename\n");
//                }
//                return -1;
            default:
                abort();
        }
    }

    if (train)
    {
        /** read train + test bmp file */
        pix = read_BMP(trainFile, &h, &w);
        if (pix == NULL)
            return -1;
        Image trainImg = getGrayLevel(pix, h, w);
        for(i = 0; i < h; i++) {
            free(pix[i]);
        }
        free(pix);
        trainImg = binarizeImage(trainImg);

        if(loopTrain){
            trainLoopProcess(trainImg, "test2.txt", nLoop);
            return 0;
        }

        pix = read_BMP(testFile, &h, &w);
        if (pix == NULL)
            return -1;
        Image testImg = getGrayLevel(pix, h, w);
        for(i = 0; i < h; i++) {
            free(pix[i]);
        }
        free(pix);
        testImg = binarizeImage(testImg);


        trainProcess(trainImg, testImg, NULL);
    }
    else if (autorun)
    {
        /// train upper network
        FILE *f = fopen("upperhid.txt", "w");
        printf("Training upper network process\n");
        minMse = 1000;
        NUM_HID_CHAR = 20;
        while (NUM_HID_CHAR < 50)
        {
            printf("Hidden node: %d\n", NUM_HID_CHAR);
            totalMse = 0;
            for (i = 0; i < trainingLoop; i++)
            {
                printf("Loop: %d\n", i);
                autoTrainProcess(NUM_TRAIN_FILE, NUM_TEST_FILE, &mse);
                totalMse += mse;
            }
            avgMse = totalMse / trainingLoop;
            fprintf(f, "hidden node = %d, average mse = %f\n", NUM_HID_CHAR, avgMse);
            NUM_HID_CHAR+=10;
        }
        fclose(f);
    }
    else if (test)
    {
        /** read input bmp file */
        pix = read_BMP(testFile, &h, &w);
        if (pix == NULL)
            return -1;
//        write_BMP("test_out.bmp",pix, h, w);
        Image inputImg = getGrayLevel(pix, h, w);
        for(i = 0; i < h; i++) {
            free(pix[i]);
        }
        free(pix);
        inputImg = filterImage(inputImg);
        inputImg = binarizeImage(inputImg);
        smoothImage(inputImg);
        printImage(inputImg, "out.txt");
        ocrProcess(inputImg);
//        charFilter();
    }
    else if (check) {
        pix = read_BMP(trainFile, &h, &w);
        if (pix == NULL)
            return -1;
        Image trainImg = getGrayLevel(pix, h, w);
        for(i = 0; i < h; i++) {
            free(pix[i]);
        }
        free(pix);
        trainImg = binarizeImage(trainImg);
        writeBinBmp(trainImg, "binImg.bmp");
        smoothImage(trainImg);
        writeBinBmp(trainImg, "smoothImg.bmp");
        int len = strlen(trainFile);
        trainFile[len-3]= 't';
        trainFile[len-2]= 'x';
        trainFile[len-1]= 't';
        checkImg(trainImg, trainFile);
    }

    return 0;
}

